summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/input_common/input_engine.cpp11
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp3
-rw-r--r--src/video_core/renderer_vulkan/vk_master_semaphore.cpp46
-rw-r--r--src/video_core/renderer_vulkan/vk_master_semaphore.h15
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h2
-rw-r--r--src/video_core/texture_cache/texture_cache.h36
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h3
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp2
10 files changed, 117 insertions, 9 deletions
diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp
index 91aa96aa7..e4c5b5b3c 100644
--- a/src/input_common/input_engine.cpp
+++ b/src/input_common/input_engine.cpp
@@ -380,13 +380,16 @@ void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int mot
if (!configuring || !mapping_callback.on_data) {
return;
}
+ const auto old_value = GetMotion(identifier, motion);
bool is_active = false;
- if (std::abs(value.accel_x) > 1.5f || std::abs(value.accel_y) > 1.5f ||
- std::abs(value.accel_z) > 1.5f) {
+ if (std::abs(value.accel_x - old_value.accel_x) > 1.5f ||
+ std::abs(value.accel_y - old_value.accel_y) > 1.5f ||
+ std::abs(value.accel_z - old_value.accel_z) > 1.5f) {
is_active = true;
}
- if (std::abs(value.gyro_x) > 0.6f || std::abs(value.gyro_y) > 0.6f ||
- std::abs(value.gyro_z) > 0.6f) {
+ if (std::abs(value.gyro_x - old_value.gyro_x) > 0.6f ||
+ std::abs(value.gyro_y - old_value.gyro_y) > 0.6f ||
+ std::abs(value.gyro_z - old_value.gyro_z) > 0.6f) {
is_active = true;
}
if (!is_active) {
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index 1190999a8..3e9b3302b 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -144,6 +144,10 @@ public:
return state_tracker;
}
+ void BarrierFeedbackLoop() const noexcept {
+ // OpenGL does not require a barrier for attachment feedback loops.
+ }
+
private:
struct StagingBuffers {
explicit StagingBuffers(GLenum storage_flags_, GLenum map_flags_);
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index f1bcd5cd6..506b78f08 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -481,12 +481,13 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
if constexpr (Spec::enabled_stages[4]) {
prepare_stage(4);
}
+ texture_cache.UpdateRenderTargets(false);
+ texture_cache.CheckFeedbackLoop(views);
ConfigureDraw(rescaling, render_area);
}
void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
const RenderAreaPushConstant& render_area) {
- texture_cache.UpdateRenderTargets(false);
scheduler.RequestRenderpass(texture_cache.GetFramebuffer());
if (!is_built.load(std::memory_order::relaxed)) {
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
index 47c74e4d8..8b65aeaeb 100644
--- a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
+++ b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
@@ -10,11 +10,16 @@
namespace Vulkan {
+constexpr u64 FENCE_RESERVE_SIZE = 8;
+
MasterSemaphore::MasterSemaphore(const Device& device_) : device(device_) {
if (!device.HasTimelineSemaphore()) {
static constexpr VkFenceCreateInfo fence_ci{
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, .pNext = nullptr, .flags = 0};
- fence = device.GetLogical().CreateFence(fence_ci);
+ free_queue.resize(FENCE_RESERVE_SIZE);
+ std::ranges::generate(free_queue,
+ [&] { return device.GetLogical().CreateFence(fence_ci); });
+ wait_thread = std::jthread([this](std::stop_token token) { WaitThread(token); });
return;
}
@@ -167,16 +172,53 @@ VkResult MasterSemaphore::SubmitQueueFence(vk::CommandBuffer& cmdbuf, VkSemaphor
.pSignalSemaphores = &signal_semaphore,
};
+ auto fence = GetFreeFence();
auto result = device.GetGraphicsQueue().Submit(submit_info, *fence);
if (result == VK_SUCCESS) {
+ std::scoped_lock lock{wait_mutex};
+ wait_queue.emplace(host_tick, std::move(fence));
+ wait_cv.notify_one();
+ }
+
+ return result;
+}
+
+void MasterSemaphore::WaitThread(std::stop_token token) {
+ while (!token.stop_requested()) {
+ u64 host_tick;
+ vk::Fence fence;
+ {
+ std::unique_lock lock{wait_mutex};
+ Common::CondvarWait(wait_cv, lock, token, [this] { return !wait_queue.empty(); });
+ if (token.stop_requested()) {
+ return;
+ }
+ std::tie(host_tick, fence) = std::move(wait_queue.front());
+ wait_queue.pop();
+ }
+
fence.Wait();
fence.Reset();
gpu_tick.store(host_tick);
gpu_tick.notify_all();
+
+ std::scoped_lock lock{free_mutex};
+ free_queue.push_front(std::move(fence));
}
+}
- return result;
+vk::Fence MasterSemaphore::GetFreeFence() {
+ std::scoped_lock lock{free_mutex};
+ if (free_queue.empty()) {
+ static constexpr VkFenceCreateInfo fence_ci{
+ .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, .pNext = nullptr, .flags = 0};
+ return device.GetLogical().CreateFence(fence_ci);
+ }
+
+ auto fence = std::move(free_queue.back());
+ free_queue.pop_back();
+ return fence;
}
} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.h b/src/video_core/renderer_vulkan/vk_master_semaphore.h
index f2f61f781..1e7c90215 100644
--- a/src/video_core/renderer_vulkan/vk_master_semaphore.h
+++ b/src/video_core/renderer_vulkan/vk_master_semaphore.h
@@ -5,8 +5,10 @@
#include <atomic>
#include <condition_variable>
+#include <deque>
#include <mutex>
#include <thread>
+#include <queue>
#include "common/common_types.h"
#include "common/polyfill_thread.h"
@@ -17,6 +19,8 @@ namespace Vulkan {
class Device;
class MasterSemaphore {
+ using Waitable = std::pair<u64, vk::Fence>;
+
public:
explicit MasterSemaphore(const Device& device);
~MasterSemaphore();
@@ -57,13 +61,22 @@ private:
VkResult SubmitQueueFence(vk::CommandBuffer& cmdbuf, VkSemaphore signal_semaphore,
VkSemaphore wait_semaphore, u64 host_tick);
+ void WaitThread(std::stop_token token);
+
+ vk::Fence GetFreeFence();
+
private:
const Device& device; ///< Device.
- vk::Fence fence; ///< Fence.
vk::Semaphore semaphore; ///< Timeline semaphore.
std::atomic<u64> gpu_tick{0}; ///< Current known GPU tick.
std::atomic<u64> current_tick{1}; ///< Current logical tick.
+ std::mutex wait_mutex;
+ std::mutex free_mutex;
+ std::condition_variable_any wait_cv;
+ std::queue<Waitable> wait_queue; ///< Queue for the fences to be waited on by the wait thread.
+ std::deque<vk::Fence> free_queue; ///< Holds available fences for submission.
std::jthread debug_thread; ///< Debug thread to workaround validation layer bugs.
+ std::jthread wait_thread; ///< Helper thread that waits for submitted fences.
};
} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 77d72697e..8711e2a87 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -861,6 +861,10 @@ VkBuffer TextureCacheRuntime::GetTemporaryBuffer(size_t needed_size) {
return *buffers[level];
}
+void TextureCacheRuntime::BarrierFeedbackLoop() {
+ scheduler.RequestOutsideRenderPassOperationContext();
+}
+
void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src,
std::span<const VideoCommon::ImageCopy> copies) {
std::vector<VkBufferImageCopy> vk_in_copies(copies.size());
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index 4166b3d20..0f7a5ffd4 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -103,6 +103,8 @@ public:
[[nodiscard]] VkBuffer GetTemporaryBuffer(size_t needed_size);
+ void BarrierFeedbackLoop();
+
const Device& device;
Scheduler& scheduler;
MemoryAllocator& memory_allocator;
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index b24086fce..8e62a5f78 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -184,6 +184,42 @@ void TextureCache<P>::FillComputeImageViews(std::span<ImageViewInOut> views) {
}
template <class P>
+void TextureCache<P>::CheckFeedbackLoop(std::span<const ImageViewInOut> views) {
+ const bool requires_barrier = [&] {
+ for (const auto& view : views) {
+ if (!view.id) {
+ continue;
+ }
+ auto& image_view = slot_image_views[view.id];
+
+ // Check color targets
+ for (const auto& ct_view_id : render_targets.color_buffer_ids) {
+ if (ct_view_id) {
+ auto& ct_view = slot_image_views[ct_view_id];
+ if (image_view.image_id == ct_view.image_id) {
+ return true;
+ }
+ }
+ }
+
+ // Check zeta target
+ if (render_targets.depth_buffer_id) {
+ auto& zt_view = slot_image_views[render_targets.depth_buffer_id];
+ if (image_view.image_id == zt_view.image_id) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }();
+
+ if (requires_barrier) {
+ runtime.BarrierFeedbackLoop();
+ }
+}
+
+template <class P>
typename P::Sampler* TextureCache<P>::GetGraphicsSampler(u32 index) {
if (index > channel_state->graphics_sampler_table.Limit()) {
LOG_DEBUG(HW_GPU, "Invalid sampler index={}", index);
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h
index 0720494e5..1a3308e2d 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -148,6 +148,9 @@ public:
/// Fill image_view_ids with the compute images in indices
void FillComputeImageViews(std::span<ImageViewInOut> views);
+ /// Handle feedback loops during draws.
+ void CheckFeedbackLoop(std::span<const ImageViewInOut> views);
+
/// Get the sampler from the graphics descriptor table in the specified index
Sampler* GetGraphicsSampler(u32 index);
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index b49f78bc9..3a7c2dedf 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -1040,7 +1040,7 @@ void Device::CollectPhysicalMemoryInfo() {
}
const s64 available_memory = static_cast<s64>(device_access_memory - device_initial_usage);
device_access_memory = static_cast<u64>(std::max<s64>(
- std::min<s64>(available_memory - 8_GiB, 4_GiB), static_cast<s64>(local_memory)));
+ std::min<s64>(available_memory - 8_GiB, 4_GiB), std::min<s64>(local_memory, 4_GiB)));
}
void Device::CollectToolingInfo() {